﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "Coordinate3d.h"
#include "GcmpGeometryInterface.h"
#include "ILine3d.h"
#include "IPolygon.h"
#include "ICurve2d.h"
#include "ICurve3d.h"
#include "ISurface.h"
#include "ILine2d.h"

namespace gcmp
{
    class IFace;
    class IPlane;
    class IBody;
    enum class GeometryErrorCode;

    /// \brief 几何投影类，用于计算几何对象的投影
    class IProject
    {
    public:
        virtual ~IProject() {};

    public:

        /// \brief  点向直线的投影
        /// \param     point           点
        /// \param     pLine3d         直线
        /// \param     param           投影点的参数
        /// \param     projectedPoint  投影点
        /// \return    成功返回true，失败返回false
        virtual bool Project(const Vector3d& point, const ILine3d* pLine3d, double& parameter, Vector3d& projectedPoint) const = 0;

        /// \brief  点向平面上投影（平面视为无限大处理）
        ///
        /// \param   point           点
        /// \param   pPlane          平面
        /// \param   uvParameter     投影点的参数
        /// \param   projectedPoint  投影点
        /// \param   投影点
        virtual bool Project(const Vector3d& point, const IPlane* pPlane, Vector2d& uvParameter, Vector3d& projectedPoint) const = 0;

        /// \brief  点沿某一方向向平面上投影（平面视为无限大处理）
        ///
        /// \param   point                  点
        /// \param   projectingDirection    投影方向
        /// \param   pPlane                 平面
        /// \param   uvParameter            投影点的参数
        /// \param   projectedPoint         投影点
        /// \param   投影点
        virtual bool Project(const Vector3d& point, const Vector3d& projectingDirection, const IPlane* pPlane, Vector2d& uvParameter, Vector3d& projectedPoint) const = 0;

        /// \brief  三维曲线向平面投影
        ///
        /// \param pCurve3d  三维曲线
        /// \param pPlane    平面
        /// \return    投影曲线
        virtual OwnerPtr<ICurve2d> Project(const ICurve3d* pICurve3d, const IPlane* pPlane) const = 0;

        /// \brief  三维曲线向平面上定向投影
        ///
        /// \param pCurve3d    三维曲线
        /// \param projectingDirection     投影方向（单位向量）
        /// \param pPlane      平面
        /// \param bNormalize  目标二维曲线是否正则化处理，默认为true
        /// \return 投影曲线
        virtual OwnerPtr<ICurve2d> Project(const ICurve3d* pCurve3d, const Vector3d& projectingDirection, const IPlane* pPlane, bool bNormalize) const = 0;

        /// \brief  三维曲线向平面投影
        ///
        /// \param pPlane    平面
        /// \param pCurve3d  三维曲线
        /// \return    投影曲线（三维曲线）
        virtual OwnerPtr<ICurve3d> ProjectReturnCurve3d(const ICurve3d* pCurve3d, const ISurface* pSurface) const = 0;

        /// \brief  局部坐标系下多边形沿给定方向平行投影到目标坐标系XoY平面
        /// \param coordinate3dFrom        原坐标系
        /// \param pPolygonFrom            原多边形
        /// \param coordinate3dTo          目标坐标系
        /// \param projectDirection        投影方向, 单位向量
        /// \return    投影多边形
        virtual OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3dFrom, const IPolygon* pPolygonFrom,
            const Coordinate3d& coordinate3dTo, const Vector3d& projectDirection) const = 0;

        /// \brief  拓扑面向平面投影(拓扑面必须与平面垂直且拓扑面的几何曲面类型为平面)
        /// \param pPlane    平面
        /// \param pFace     面
        /// \return    投影直线
        virtual OwnerPtr<ILine3d> Project(const IPlane* pPlane, const IFace* pFace) const = 0;

        /// \brief  体向局部坐标系投影
        /// \param coordinate3d      局部坐标系
        /// \param constpBody        体
        /// \return    投影多边形
        virtual OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3d, const IBody* pBody) const = 0;

        /// \brief  拓扑面向局部坐标系投影
        /// \param coordinate3d      局部坐标系
        /// \param pFace             拓扑面
        /// \return    投影多边形
        virtual OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3d, const IFace* pFace) const = 0;

        /// \brief  将二维曲线投影到直线上
        ///
        /// \param pCurve    待投影的曲线
        /// \param pLine     投影目标直线
        /// \return  投影后的二维直线
        virtual OwnerPtr<ILine2d> ProjectCurve2dToLine(const ICurve2d* pCurve, const ILine2d* pLine) const = 0;

        /// \brief  沿源坐标系Z向平行投影二维曲线到目标坐标系XY平面
        /// \param[in] planeFrom    源坐标系
        /// \param[in] curveFrom    源二维曲线
        /// \param[in] planeTo      目标坐标系
        /// \param[in] vProjDir     投影方向
        /// \return    目标二维曲线
        virtual OwnerPtr<ICurve2d>  Project(const Coordinate3d& planeFrom, const ICurve2d* curveFrom, const Coordinate3d& planeTo, const Vector3d& vProjDir) const = 0;
        
        /// \brief  线框体投影
        /// \param[in] wireBody         线框体
        /// \param[in] targetBody       目标体，类型为Solid
        /// \param[in] projDir          投影方向
        /// \param[in] supportFaces     指定的投影面集合，投影面须存在于目标体上。若设置为null，则默认为目标体上的所有面。
        /// \param[in] projectBodies    投影后的体
        /// \return    投影错误码
        virtual GeometryErrorCode  Project(const IBody* wireBody, const IBody* targetBody, const Vector3d& projDir, const std::vector<IFace*>& supportFaces, std::vector<OwnerPtr<IBody>>& projectBodies) const = 0;

    protected:
        /// \brief  三维曲线向曲面投影（三维曲线仅限Line3d、Arc3d和Ellipse3d）
        /// \param  pCurve3d                         三维曲线
        /// \param  pSurface                         曲面
        /// \param  projectedDirection               投影方向
        /// \param  bTrimCurve                       是否对被遮挡的投影曲线进行裁剪
        /// \return    投影曲线
        virtual std::vector<OwnerPtr<ICurve3d>> Project(const ICurve3d* pCurve3d, const ISurface* pSurface, const Vector3d &projectedDirection, bool bTrimCurve) const = 0;
    };
}
